const { NacosNamingClient, NacosConfigClient } = require('nacos')
const R = require('ramda')
const axios = require('axios').default
const sleep = require('sleep')
module.exports = ({ logger, config }) => {
  if (config.get('useNacos') === 0) return null

  const { url, namespace, dataId, groupId } = config.get('nacos')
  const serviceName = config.get('serviceName')
  const ip = config.get('ip')
  const port = config.get('port')
  const serviceClient = new NacosNamingClient({
    logger: logger,
    serverList: url,
    namespace,
  })

  const log = (message) => {
    logger.info(`[Nacos] ${message}`)
  }

  const configClient = new NacosConfigClient({
    serverAddr: url,
  })

  let isSuccess = false
  let retryCount = 0
  const checkNacosServerStatus = async () => {
    if (retryCount === 5) {
      log(`链接失败，退出程序`)
      process.exit(0)
    }
    const status = await serviceClient.getServerStatus()
    isSuccess = status === 'UP'
    log(`正在第${++retryCount}次检查服务器 ${url} 状态: ${status}`)
    if (!isSuccess) {
      sleep.sleep(1)
      await checkNacosServerStatus()
    }
    log(`检查服务器 ${url} 状态: ${status}`)
  }
  const register = async () => {
    log(`注册服务 《${serviceName}》 ----> ${url}`)
    await serviceClient.registerInstance(serviceName, {
      ip,
      port: config.get('port'),
    })
    // await loadConfig()
  }
  let initial = false
  const nacos = {
    up: async (handle) => {
      await serviceClient.ready()
      await checkNacosServerStatus()
      configClient.subscribe({ dataId, group: groupId }, async (content) => {
        try {
          const nacosConfig = JSON.parse(content)
          log(`更新配置`)
          config.load(nacosConfig)
          console.log('最新配置', nacosConfig)
          if (!initial) {
            if (handle) {
              await nacos.down()
              await register()
              await handle()
              initial = true
            }
          } else {
            log('配置重新改动，准备重启服务....')
            setTimeout(() => {
              process.exit(0)
            }, 1000)
          }
        } catch (error) {
          logger.error(error.stack)
          process.exit(0)
        }
      })
    },
    serviceClient,
    configClient,
    down: async () => {
      await serviceClient.deregisterInstance(serviceName, {
        ip,
        port,
      })
    },
    getClient: async (...args) => {
      const serviceList = await serviceClient.getAllInstances(...args)
      const filterList = serviceList.filter(
        (item) => item.healthy && item.enabled
      )
      if (filterList.length) {
        const serviceHost = R.compose(
          (hostname) => `http://${hostname}`,
          R.join(':'),
          R.values,
          R.pick(['ip', 'port']),
          R.head
        )(filterList)
        const client = axios.create({
          baseURL: serviceHost,
        })
        client.interceptors.response.use((res) => {
          return res.data
        })
        return client
      }
    },
  }
  return nacos
}
